﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using GraphCompiler.Core.Exceptions;

namespace GraphCompiler.Core
{
    public class TokenCollection : IEnumerable<Token>
    {
        List<Token> _tokens = new List<Token>();

        public TokenCollection()
        {

        }

        public TokenCollection(params string[] tokenStrings)
        {
            foreach (string tokenString in tokenStrings)
                Add(new Token(tokenString));
        }

        public void Add(Token token)
        {
            _tokens.Add(token);
        }

        public IEnumerator<Token> GetEnumerator()
        {
            return _tokens.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _tokens.GetEnumerator();
        }

        public bool IsEmpty
        {
            get
            {
                return _tokens.Count == 0;
            }
        }

        public bool IsNextTokenClosingBracket
        {
            get
            {
                if (_tokens.Count == 0)
                    return false;

                return _tokens[0].Equals(new Token("}"));
            }
        }

        public void ConsumeNext(string expectedTokenString)
        {
            var readToken = _tokens[0];
            _tokens.RemoveAt(0);

            var expectedToken = new Token(expectedTokenString);

            if (!readToken.Equals(expectedToken))
            {
                string errorMessage = string.Format("expected: {0} but was: {1}", expectedTokenString, readToken.String);
                throw new SyntaxErrorException(errorMessage);
            }
        }

        public void ConsumeNext()
        {
            _tokens.RemoveAt(0);
        }

        public Token ReadNext()
        {
            if (IsEmpty)
                throw new SyntaxErrorException();
            
            var readToken = _tokens[0];
            ConsumeNext();

            return readToken;
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }

            var other = obj as TokenCollection;

            if (this._tokens.Count != other._tokens.Count)
                return false;

            for (int i = 0; i < _tokens.Count; i++)
            {
                if (!_tokens[i].Equals(other._tokens[i]))
                    return false;
            }

            return true;
        }
    }
}